﻿using System.Collections.Generic;

namespace PhiStore.Policies
{
    /// <summary>
    /// A collection of example policies
    /// </summary>
    public static class Examples
    {
        /// <summary>
        /// All variants of policies
        /// </summary>
        /// <param name="DefaultIdleThreshold"></param>
        /// <param name="DefaultReplicationNumber"></param>
        /// <returns></returns>
        public static List<Policy> AllVariants(ulong DefaultIdleThreshold,
                                                uint DefaultReplicationNumber)
        {
            List<bool[]> variants = new List<bool[]>();
            variants.Add(new bool[] { false, false, false });
            variants.Add(new bool[] { false, false, true });
            variants.Add(new bool[] { false, true, false });
            variants.Add(new bool[] { false, true, true });
            variants.Add(new bool[] { true, false, false });
            variants.Add(new bool[] { true, false, true });
            variants.Add(new bool[] { true, true, false });
            variants.Add(new bool[] { true, true, true });

            List<Policy> result = new List<Policy>();
            foreach (bool[] variant in variants)
            {
                result.AddRange(AllCapabilityVariants(
                    variant[0],
                    variant[1],
                    DefaultIdleThreshold,
                    DefaultReplicationNumber,
                    variant[2]));
            }
            return result;
        }

        /// <summary>
        /// All capability variants of policies
        /// </summary>
        /// <param name="DefaultEnforceAtomicity"></param>
        /// <param name="DefaultFastReturn"></param>
        /// <param name="DefaultIdleThreshold"></param>
        /// <param name="DefaultReplicationNumber"></param>
        /// <param name="DefaultMayGarbageCollect"></param>
        /// <returns></returns>
        public static List<Policy> AllCapabilityVariants(bool DefaultEnforceAtomicity,
                                                         bool DefaultFastReturn,
                                                         ulong DefaultIdleThreshold,
                                                         uint DefaultReplicationNumber,
                                                         bool DefaultMayGarbageCollect)
        {
            Policy policy = new Policy();
            policy.EnforceAtomicity = DefaultEnforceAtomicity;
            policy.FastReturn = DefaultFastReturn;
            policy.ReplicationNumber = DefaultReplicationNumber;
            policy.IdleThreshold = DefaultIdleThreshold;
            policy.MayGarbageCollect = DefaultMayGarbageCollect;

            List<bool[]> variants = new List<bool[]>();

            variants.Add(new bool[] { false, false, false, false });
            variants.Add(new bool[] { false, false, false, true });
            variants.Add(new bool[] { false, false, true, false });
            variants.Add(new bool[] { false, false, true, true });
            variants.Add(new bool[] { false, true, false, false });
            variants.Add(new bool[] { false, true, false, true });
            variants.Add(new bool[] { false, true, true, false });
            variants.Add(new bool[] { false, true, true, true });

            variants.Add(new bool[] { true, false, false, false });
            variants.Add(new bool[] { true, false, false, true });
            variants.Add(new bool[] { true, false, true, false });
            variants.Add(new bool[] { true, false, true, true });
            variants.Add(new bool[] { true, true, false, false });
            variants.Add(new bool[] { true, true, false, true });
            variants.Add(new bool[] { true, true, true, false });
            variants.Add(new bool[] { true, true, true, true });


            List<Policy> result = new List<Policy>();
            foreach (bool[] variant in variants)
            {
                policy = policy.Copy();

                policy.MayAppend = variant[0];
                policy.MayDelete = variant[1];
                policy.MayModify = variant[2];
                policy.MayPop = variant[3];
                
                result.Add(policy);
            }

            return result;
        }

        /// <summary>
        /// Policy where the actions allowed are those you would expect from a queue
        /// </summary>
        public static Policy Queue
        {
            get
            {
                Policy result = new Policy();
                result.EnforceAtomicity = true;
                result.FastReturn = false;
                result.IdleThreshold = 10 * 60 * 1000;
                result.MayAppend = true;
                result.MayGarbageCollect = true;
                result.MayDelete = false;
                result.MayModify = false;
                result.MayPop = true;
                result.ReplicationNumber = 1;
                return result;
            }
        }

        /// <summary>
        /// Policy for a persistent value
        /// </summary>
        public static Policy PersistentValue
        {
            get
            {
                Policy result = new Policy();
                result.EnforceAtomicity = true;
                result.FastReturn = false;
                result.IdleThreshold = 10 * 60 * 1000;
                result.MayAppend = false;
                result.MayGarbageCollect = false;
                result.MayDelete = false;
                result.MayModify = false;
                result.MayPop = false;
                result.ReplicationNumber = 1;
                return result;
            }
        }

        /// <summary>
        /// Fixes size list.
        /// NOTE: Complete deletion relies on Garbage Collection
        /// </summary>
        public static Policy Array
        {
            get
            {
                Policy result = new Policy();
                result.EnforceAtomicity = true;
                result.FastReturn = false;
                result.IdleThreshold = 10 * 60 * 1000;
                result.MayAppend = false;
                result.MayGarbageCollect = true;
                result.MayDelete = false;
                result.MayModify = true;
                result.MayPop = false;
                result.ReplicationNumber = 1;
                return result;
            }
        }

        /// <summary>
        /// Policy for a list
        /// </summary>
        public static Policy List
        {
            get
            {
                Policy result = new Policy();
                result.EnforceAtomicity = true;
                result.FastReturn = false;
                result.IdleThreshold = 10 * 60 * 1000;
                result.MayAppend = true;
                result.MayGarbageCollect = true;
                result.MayDelete = true;
                result.MayModify = true;
                result.MayPop = false;
                result.ReplicationNumber = 1;
                return result;
            }
        }

        /// <summary>
        /// Policy for a log ( append only)
        /// </summary>
        public static Policy Log
        {
            get
            {
                Policy result = new Policy();
                result.EnforceAtomicity = true;
                result.FastReturn = false;
                result.IdleThreshold = 10 * 60 * 1000;
                result.MayAppend = true;
                result.MayGarbageCollect = true;
                result.MayDelete = false;
                result.MayModify = false;
                result.MayPop = false;
                result.ReplicationNumber = 1;
                return result;
            }
        }

        /// <summary>
        /// Fastest possible policy (no 2PC + FastReturn)
        /// </summary>
        public static Policy FastAsHell
        {
            get
            {
                Policy result = new Policy();
                result.EnforceAtomicity = false;
                result.FastReturn = true;
                result.IdleThreshold = 10 * 60 * 1000;
                result.MayAppend = true;
                result.MayGarbageCollect = true;
                result.MayDelete = true;
                result.MayModify = true;
                result.MayPop = true;
                result.ReplicationNumber = 1;
                return result;
            }
        }

    }
}
